Service.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. "use client";
  2. import { getWheelApi } from "@/api/cashWheel";
  3. import { ServiceTypes } from "@/api/customservice";
  4. import { lredPacketApi, redPacketApi } from "@/api/promo";
  5. import { getGiveInfoApi } from "@/api/slots";
  6. import { Timeout } from "@/components/ModalPopup/RechargeModal";
  7. import RedPacketModal, { RedPacketModalProps } from "@/components/ModalPopup/RedPacketModal";
  8. import SlotsModal, { SlotModalRefProps } from "@/components/ModalPopup/SlotsModal";
  9. import dialogManage from "@/dialog/manager";
  10. import { useEventPoint } from "@/hooks/useEventPoint";
  11. import { Link } from "@/i18n/routing";
  12. import { useFirstPayStore } from "@/stores/useFirstPayStore";
  13. import { useGlobalNoticeStore } from "@/stores/useGlobalNoticeStore";
  14. import useWheelStore from "@/stores/useWheelStore";
  15. import { getToken } from "@/utils/Cookies";
  16. import { useRequest } from "ahooks";
  17. import { Badge } from "antd-mobile";
  18. import { useTranslations } from "next-intl";
  19. import Image from "next/image";
  20. import { FC, useEffect, useRef, useState } from "react";
  21. interface Props {
  22. services: ServiceTypes[];
  23. }
  24. interface SlotSectionProps {
  25. onDestory?: () => void;
  26. }
  27. /**
  28. * 免费送活动
  29. */
  30. const SlotSection: FC<SlotSectionProps> = ({ onDestory }) => {
  31. const slotsRef = useRef<SlotModalRefProps | null>(null);
  32. const getSlots = async () => {
  33. const token = getToken();
  34. if (token) {
  35. const result = await getGiveInfoApi();
  36. return result.data;
  37. } else {
  38. destory();
  39. return Promise.resolve({});
  40. }
  41. };
  42. const { data: slots, run: slotRun } = useRequest<any, any>(getSlots, {
  43. pollingInterval: 2000,
  44. pollingErrorRetryCount: 1,
  45. });
  46. const slotHandler = () => {
  47. slotsRef.current?.onOpen(slots);
  48. };
  49. const destory = () => {
  50. if (onDestory && typeof onDestory === "function") onDestory();
  51. };
  52. return (
  53. <>
  54. {slots?.id ? (
  55. <img
  56. src={"/slots/slots-icon.gif"}
  57. className={"mb-[0.2778rem] w-[100%]"}
  58. onClick={slotHandler}
  59. alt=""
  60. />
  61. ) : null}
  62. {/*随机送*/}
  63. <SlotsModal ref={slotsRef} onAfterHandler={slotRun} onClose={destory} />
  64. </>
  65. );
  66. };
  67. /**
  68. * 轮盘
  69. */
  70. const WheelSection = () => {
  71. const { wheelStatus } = useWheelStore((state) => ({
  72. wheelStatus: state.status,
  73. }));
  74. return (
  75. <>
  76. {wheelStatus === 2 ? (
  77. <Link
  78. href={"/cashWheel"}
  79. className={
  80. "mb-[0.2778rem] flex h-[0.54rem] w-[0.54rem] items-center" +
  81. " justify-center rounded-[50%] bg-gradient-to-b from-[#0575e6] to-[#00f260]"
  82. }
  83. >
  84. <Image src={"/wheels/wheel-icon.gif"} alt={"wheel"} width={100} height={100} />
  85. </Link>
  86. ) : null}
  87. </>
  88. );
  89. };
  90. /**
  91. * 首充
  92. */
  93. const PaySection = () => {
  94. const token = getToken();
  95. const { firstPay, getPayData } = useFirstPayStore((state) => {
  96. return {
  97. firstPay: state.first_pay,
  98. getPayData: state.getPayData,
  99. };
  100. });
  101. const { data, run: payRun } = useRequest(getPayData, {
  102. pollingErrorRetryCount: 1,
  103. pollingWhenHidden: false,
  104. });
  105. return (
  106. <>
  107. {firstPay.map((item, index) => {
  108. return (
  109. <div
  110. key={index}
  111. className={`mb-[0.2778rem] flex cursor-pointer flex-col items-center`}
  112. >
  113. <img
  114. className={"w-[0.54rem]"}
  115. src="/hby/recharge.png"
  116. onClick={() => {
  117. dialogManage.showDialog("PaySection", firstPay, index);
  118. // userRechargeRef.current?.onOpen &&
  119. // userRechargeRef.current?.onOpen(firstPay, index);
  120. }}
  121. alt=""
  122. />
  123. {item.count_down > 0 ? (
  124. <Timeout
  125. className={
  126. "relative before:left-0 before:top-0 before:content-['']" +
  127. " -m-[0.0417rem] before:h-[100%] before:blur-[0.0486rem]" +
  128. " before:absolute before:-z-10 before:w-[100%] before:bg-[#ed9d00]" +
  129. " text-[0.08rem]" +
  130. " z-1 text-[#fff]"
  131. }
  132. endTime={item.count_down}
  133. onEndHandler={payRun}
  134. />
  135. ) : null}
  136. </div>
  137. );
  138. })}
  139. </>
  140. );
  141. };
  142. /**
  143. * 红包雨
  144. */
  145. const RedPacketSection = () => {
  146. const token = getToken();
  147. const redPacketModalRef = useRef<RedPacketModalProps>(null);
  148. const getRedPacketInfo = async () => {
  149. try {
  150. let redPacketInfo: any;
  151. let actList: any = [];
  152. if (token) {
  153. redPacketInfo = await lredPacketApi();
  154. actList = redPacketInfo.data?.red_packets || [];
  155. } else {
  156. redPacketInfo = await redPacketApi();
  157. actList = redPacketInfo.data || [];
  158. }
  159. // 已经开始
  160. return actList.filter((aItem: any) => {
  161. return aItem.is_start;
  162. });
  163. } catch (error) {}
  164. };
  165. // 红包雨轮询
  166. const { data: packets, run } = useRequest<any[], any>(getRedPacketInfo, {
  167. pollingInterval: 5000,
  168. pollingErrorRetryCount: 1,
  169. pollingWhenHidden: false,
  170. });
  171. return (
  172. <>
  173. {packets?.map((item, index) => {
  174. const icons = JSON.parse(item.icon);
  175. const icon = icons[icons.length - 1];
  176. return (
  177. <div key={index} className={`mb-[0.2778rem] cursor-pointer`}>
  178. <img
  179. className={"w-[0.54rem] object-fill"}
  180. src={icon}
  181. onClick={() => {
  182. redPacketModalRef.current?.onOpen(packets, index);
  183. }}
  184. alt=""
  185. />
  186. </div>
  187. );
  188. })}
  189. {/*红包雨弹窗*/}
  190. <RedPacketModal ref={redPacketModalRef} onAfterHandler={run} />
  191. </>
  192. );
  193. };
  194. const MessageSection = () => {
  195. const { unread, userUnred } = useGlobalNoticeStore((state) => ({
  196. unread: state.unread,
  197. userUnred: state.userUnred,
  198. }));
  199. return (
  200. <>
  201. {unread || userUnred ? (
  202. <Link
  203. href={"/notification"}
  204. className={
  205. "mb-[0.2778rem] flex h-[0.54rem] w-[0.54rem] items-center" +
  206. " justify-center rounded-[50%] bg-gradient-to-t from-[#ffa111]" +
  207. " to-[#ffcf35]"
  208. }
  209. >
  210. <Badge content={userUnred + unread} style={{ "--top": "12px" }}>
  211. <i className={"iconfont icon-duanxinguanli text-[0.3rem] text-[#fff]"}></i>
  212. </Badge>
  213. </Link>
  214. ) : null}
  215. </>
  216. );
  217. };
  218. /**
  219. * 客服
  220. */
  221. const CustomerSection: FC<Omit<Props, "socials">> = (props) => {
  222. const { services } = props;
  223. const defaultService = services?.filter((item) => item.is_suspend === 1);
  224. return (
  225. <>
  226. {defaultService?.map((item, index) => (
  227. <Link
  228. key={index}
  229. href={item.url}
  230. className={
  231. "flex h-[0.54rem] w-[0.54rem] items-center justify-center rounded-[50%]" +
  232. " bg-gradient-to-t from-[#ff611b] to-[#ffcf35]"
  233. }
  234. target={"_blank"}
  235. >
  236. <img
  237. className={"h-[0.3889rem] w-[0.3889rem] object-contain"}
  238. src={item.icon_url}
  239. alt={""}
  240. ></img>
  241. </Link>
  242. ))}
  243. </>
  244. );
  245. };
  246. const ServiceWidget: FC<Props> = (props) => {
  247. const { services } = props;
  248. const [type, setType] = useState<number>(0);
  249. const { eventView } = useEventPoint();
  250. const newServices = services?.filter((item) => item.status === 1) || [];
  251. const getWheel = () => {
  252. if (!getToken()) return Promise.resolve(undefined);
  253. return getWheelApi().then((res) => {
  254. return res.data;
  255. });
  256. };
  257. useEffect(() => {
  258. // 数据存储,侧边栏使用
  259. // setSocials(socials);
  260. // pixel 埋点
  261. // eventView();
  262. }, []);
  263. const t = useTranslations("HomePage");
  264. return (
  265. <>
  266. <div
  267. className={`absolute bottom-[0.84rem] right-[0.12rem] z-50 flex w-[0.6944rem] flex-col items-center justify-center`}
  268. >
  269. {/* {React.cloneElement(curComponents, { onDestory: modalDestory })} */}
  270. <SlotSection />
  271. {/*轮盘 */}
  272. <WheelSection />
  273. {/*首充*/}
  274. <PaySection />
  275. {/* 红包雨icon */}
  276. <RedPacketSection />
  277. {/*未读消息*/}
  278. <MessageSection />
  279. {/*客服*/}
  280. <CustomerSection services={services} />
  281. {/* 签到 */}
  282. {/* <SignInSection /> */}
  283. </div>
  284. <div
  285. className={`grid`}
  286. style={{
  287. gridTemplateColumns: ` repeat(${newServices && newServices.length >= 5 ? 5 : (newServices?.length ?? 1)},1fr)`,
  288. }}
  289. >
  290. {newServices.map((service, index) => {
  291. return (
  292. <Link
  293. key={index}
  294. href={service.url}
  295. target={"_blank"}
  296. className="bg-white m-[0.05rem] h-[0.3889rem] w-[0.3889rem] rounded"
  297. >
  298. <img
  299. className={"h-[0.3889rem] w-[0.3889rem]"}
  300. src={service.icon_url}
  301. alt=""
  302. ></img>
  303. </Link>
  304. );
  305. })}
  306. </div>
  307. <div className={"text-[#ced1ff]"}>{t("Service")}</div>
  308. {/*share*/}
  309. <div className={"my-[0.2rem] text-[0.12rem] text-[#ced1ff]"}>{t("Share")}</div>
  310. <Image
  311. src={"/logo2.png"}
  312. alt={"BCWIN777"}
  313. width={120}
  314. height={180}
  315. className={"mb-[0.2rem]"}
  316. />
  317. </>
  318. );
  319. };
  320. export default ServiceWidget;